qcom-capsule: inject the OEM root cert with qdte-lite, before signing - #3043
qcom-capsule: inject the OEM root cert with qdte-lite, before signing#3043Igor Opaniuk (igoropaniuk) wants to merge 5 commits into
Conversation
|
xueqnie could you please take a look, thanks! |
Test Results 30 files - 89 30 suites - 686 2h 47m 58s ⏱️ - 11h 26m 13s For more details on these failures, see this check. Results for commit 0fd9daf. ± Comparison against base commit f00721c. This pull request removes 167 tests.♻️ This comment has been updated with latest results. |
Tested on iq-x7181-evk (hamoa). Build fails at firmware-qcom-oem-cert:do_compile |
|
Thanks for testing this on hamoa. I haven't been able to reproduce it, so I'd like to narrow down what's different in your setup. I built I also ran the failing Things I checked and ruled out:
So the remaining variable looks like the input. Could you post:
qdte-lite --nogui --input_file <that uefi_dtbs.xz> --find_property QcCapsuleRootCert
|
please check
Different from your 44984c3b…, which confirms the input is different.
|
|
xueqnie could you provide a link to that iq-x7181/spinor/uefi_dtbs.xz? |
|
|
xueqnie I found the root cause, the fix is in qualcomm/qdte-lite#4. I'll update this PR in a momemnt with this patch used in the qdte-lite recipe |
The capsule root certificate lives in a device tree embedded in a boot config ELF, so putting it there means editing a DTB inside a container the build has no tool to open. cbsp-boot-utilities can do it, but only through a fixed dump / set-property / replace sequence that has to be told which DTB to touch. qdte-lite opens these containers directly and can be asked what is in them, which is what the following commits need to find the certificate without hardcoding per-machine names. Packaging it is cheap because the fork was made for this: a pyproject with a console script, child interpreters spawned via sys.executable, and a --nogui path that never imports a GUI toolkit. Its device-tree layer is pylibfdt, so oe-core's python3-dtc is the only dependency and the recipe stays out of any dynamic layer. Carry one patch. v2.0.0 fails with FDT_ERR_NOSPACE on a tree whose serialized size happens to be an exact multiple of the 1024-byte step FdtSw grows its buffer in: every write method retries through check_space(), but as_fdt() calls fdt_finish() once and gives up if the strings block and header fixups do not fit in what is left. Nothing is wrong with such a tree, it just lands with zero slack, so this is a size lottery rather than a real limit and roughly one DTB in 256 loses it. The iq-x7181-evk 00019 boot binaries draw a losing ticket, which is why this only shows up on some machines and some firmware versions. Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
The capsule recipes sat in dynamic-layers/meta-arm for one reason: they needed edk2-basetools for GenFfs, GenFv and GenerateCapsule.py. That made capsule generation unavailable unless a consumer also carried meta-arm, which has nothing else to do with building a capsule. cbsp-boot-utilities has since grown its own equivalents -- fv_builder.py for the first two, generate-capsule for the third, byte-identical for this subset -- so the dependency is gone and with it the only reason for the recipes to live behind a layer that may not be present. Bump to pick that up and move them into the normal recipe tree. meta-arm is still needed for optee and trusted-firmware-a, so the layer stays; only the capsule pieces leave it. Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
…gned Three things have to happen in one order and cannot be reordered: the certificate goes into the boot config ELF, that ELF is signed, then the capsule is built and verified against the certificate. Editing a DTB inside the ELF invalidates any signature it already carried, so injecting after signing produces an image the boot ROM rejects; building the capsule before injection produces one the firmware will not authenticate. qcom-capsule.bbclass is the wrong place for step one, because by the time it runs the boot firmware is already deployed and whatever signs it has already finished. There is no seam left. A separate recipe between the boot firmware and the capsule creates one: it stages the injected ELFs and stops, leaving do_compile and do_deploy for a signing step to sit between. Injection itself no longer needs the class to know anything about the container. The DTB names are assigned during disassembly -- from container metadata in one case, from /compatible in another -- so asking the tool that assigns them beats configuring them per machine, which is what XBLCONFIG_DTB and XBLCONFIG_DTB_SECTION were doing and why they go away. Leaving the DER-to-cells conversion to bin-to-hex keeps the padding of a trailing partial cell in one place, where the two tools cannot disagree about it. Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
Hamoa and similar SPINOR-boot parts have no xbl_config.elf at all: their QcCapsuleRootCert lives in uefi_dtbs.elf, shipped xz-compressed. Without this the injection finds nothing to patch on those machines and the capsule is rejected at authentication time, with nothing in the build to suggest why. The container also holds the property more than once -- in a base DTB and in a .dtbo overlay, at different node paths -- so anything assuming a single target would silently patch half of it. --find_property already reports each as its own line and --modify takes them in one pass, so handling hamoa needs no machinery beyond staging the file. It deploys under its own name for the same reason xbl_config does: the boot firmware recipe owns the unmodified copy, and two recipes cannot deploy the same filename. image_types_qcom then prefers the cert-bearing one over the QCOM_UEFI_DTB variant, because a device flashed with the other will not take an update. Signed-off-by: Xueqian Nie <xueqian.nie@oss.qualcomm.com> Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
CAPSULE_FLASH_TYPE and CAPSULE_ENTRIES next to these definitions are machine-qualified; the CAPSULE_ENTRY_dtb[...] flags beside them are not, and cannot be -- varflags take no part in override resolution, so CAPSULE_ENTRY_dtb[dest_disk]:iq-x7181-evk does not exist. They therefore apply on every machine. Any other board that declares a "dtb" capsule entry inherits hamoa's SPINOR destinations, and nothing catches it: generate_fvupdate() only checks that an entry has a binary, a dest_disk and a dest_partition, all of which hamoa's values supply. The build succeeds and produces a capsule aimed at storage the machine may not even have. Guarding on MACHINEOVERRIDES gives the flags the scope the neighbouring overrides already have. Renaming the entry would also work, but the class keys the kernel dependency on the literal name "dtb". Fixes: a314263 ("firmware-qcom-capsule: add iq-x7181-evk capsule entry definitions") Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
0e66a76 to
0fd9daf
Compare
|
xueqnie I've pushed updated recipe with a fix, feel free to test on your side. Thanks! |
The OEM capsule root certificate lives in a device tree embedded in a boot config ELF (
xbl_config.elf/uefi_dtbs.elf), and getting it there constrains the whole pipeline. Three things must happen in this order:QcCapsuleRootCertinto the config ELF (xbl_config.elf/uefi_dtbs.elf)qcom-capsule.bbclasscan't own step 1: by the time it runs, the boot firmware is deployed and whatever signs it has finished. There's no seam left. This series moves injection into its own recipe between the boot firmware and the capsule, which creates one - it stages the injected ELFs and stops, leavingdo_compile/do_deployfor a signing step to sit between. That's what makes the secure-boot work in #2598 able to slot in without rewiring anything.Injection of the root certification (stored in
QcCapsuleRootCertproperty) is done byqdte-liteinstead of a fixeddump/set-property/replacesequence. The class no longer needs to know anything about the container:DTB names are assigned during disassembly - from container metadata in one container, from
/compatiblein another - so asking the tool that assigns them beats configuring them per machine.XBLCONFIG_DTBandXBLCONFIG_DTB_SECTIONgo away.Also the capsule flow leaves
meta-arm. It lived there only foredk2-basetools(GenFfs,GenFv,GenerateCapsule.py).cbsp-boot-utilitiesnow has its own equivalents, so the dependency and the reason for the dynamic layer are both gone.Additionally two bugs are fixed:
qcom-capsule.bbclasstested for a literalxbl_config.elf, butQCOM_XBL_CONFIGisxbl_config_kvm.elfon kvm machines likeiq-9075-evk- injection was silently skipped there, surfacing much later as a capsule the firmware refuses. Now usesQCOM_XBL_CONFIGthroughout.CAPSULE_ENTRY_dtb[...]flags were unqualified. Varflags take no part in override resolution, so hamoa's SPINOR destinations applied to every machine, and generate_fvupdate()doesn't catch it. Now guarded onMACHINEOVERRIDES.Can be build with this config (example for RB3Gen2):